package cn.edu.ncut.cs.springboot.petmanagementsystem.service.Impl;

import cn.edu.ncut.cs.springboot.petmanagementsystem.mapper.PetMapper;
import cn.edu.ncut.cs.springboot.petmanagementsystem.mapper.ServiceReservationMapper;
import cn.edu.ncut.cs.springboot.petmanagementsystem.mapper.ServiceTypeMapper;
import cn.edu.ncut.cs.springboot.petmanagementsystem.pojo.Pet;
import cn.edu.ncut.cs.springboot.petmanagementsystem.pojo.ServiceReservation;
import cn.edu.ncut.cs.springboot.petmanagementsystem.pojo.ServiceType;
import cn.edu.ncut.cs.springboot.petmanagementsystem.service.CalendarService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.*;

@Slf4j
@Service
public class CalendarServiceImpl implements CalendarService {

    @Autowired
    private ServiceReservationMapper reservationMapper;

    @Autowired
    private ServiceTypeMapper serviceTypeMapper;

    @Autowired
    private PetMapper petMapper;

    @Override
    public Map<String, Object> getMonthCalendar(Integer year, Integer month) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 验证参数
            if (year == null || month == null || month < 1 || month > 12) {
                result.put("error", "参数错误");
                return result;
            }

            YearMonth yearMonth = YearMonth.of(year, month);
            LocalDate startDate = yearMonth.atDay(1);
            LocalDate endDate = yearMonth.atEndOfMonth();

            // 查询该月的所有预约（包括待确认、已确认、进行中的预约）
            LambdaQueryWrapper<ServiceReservation> wrapper = new LambdaQueryWrapper<>();
            wrapper.between(ServiceReservation::getReservationDate, startDate, endDate);
            wrapper.in(ServiceReservation::getReservationStatus, Arrays.asList(1, 2, 3, 4)); // 待确认、已确认、进行中、已完成
            
            List<ServiceReservation> reservations = reservationMapper.selectList(wrapper);

            // 按日期分组统计预约数量
            Map<String, Integer> dateCountMap = new HashMap<>();
            Map<String, List<Map<String, Object>>> dateDetailsMap = new HashMap<>();

            for (ServiceReservation reservation : reservations) {
                String dateStr = reservation.getReservationDate().toString();
                dateCountMap.put(dateStr, dateCountMap.getOrDefault(dateStr, 0) + 1);

                // 获取服务类型信息
                ServiceType serviceType = serviceTypeMapper.selectById(reservation.getServiceTypeId());
                Pet pet = petMapper.selectById(reservation.getPetId());

                Map<String, Object> detail = new HashMap<>();
                detail.put("id", reservation.getId());
                detail.put("reservationNo", reservation.getReservationNo());
                detail.put("serviceTypeId", reservation.getServiceTypeId());
                detail.put("serviceTypeName", serviceType != null ? serviceType.getServiceName() : "未知服务");
                detail.put("petId", reservation.getPetId());
                detail.put("petName", pet != null ? pet.getPetName() : "未知宠物");
                detail.put("reservationTime", reservation.getReservationTime() != null ? 
                    reservation.getReservationTime().toString() : "");
                detail.put("status", reservation.getReservationStatus());
                detail.put("statusText", getStatusText(reservation.getReservationStatus()));

                dateDetailsMap.computeIfAbsent(dateStr, k -> new ArrayList<>()).add(detail);
            }

            // 构建日历数据
            List<Map<String, Object>> calendarDays = new ArrayList<>();
            int daysInMonth = yearMonth.lengthOfMonth();
            
            for (int day = 1; day <= daysInMonth; day++) {
                LocalDate currentDate = yearMonth.atDay(day);
                String dateStr = currentDate.toString();
                
                Map<String, Object> dayInfo = new HashMap<>();
                dayInfo.put("date", dateStr);
                dayInfo.put("day", day);
                dayInfo.put("dayOfWeek", currentDate.getDayOfWeek().getValue()); // 1=Monday, 7=Sunday
                dayInfo.put("count", dateCountMap.getOrDefault(dateStr, 0));
                dayInfo.put("isToday", currentDate.equals(LocalDate.now()));
                dayInfo.put("isPast", currentDate.isBefore(LocalDate.now()));
                dayInfo.put("reservations", dateDetailsMap.getOrDefault(dateStr, new ArrayList<>()));
                
                calendarDays.add(dayInfo);
            }

            result.put("year", year);
            result.put("month", month);
            result.put("yearMonth", yearMonth.toString());
            result.put("daysInMonth", daysInMonth);
            result.put("firstDayOfWeek", startDate.getDayOfWeek().getValue());
            result.put("calendarDays", calendarDays);
            result.put("totalReservations", reservations.size());

        } catch (Exception e) {
            log.error("获取月度预约日历失败", e);
            result.put("error", "查询失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public List<Map<String, Object>> getUserSchedule(Long userId, LocalDate startDate, LocalDate endDate) {
        List<Map<String, Object>> scheduleList = new ArrayList<>();

        try {
            if (userId == null) {
                return scheduleList;
            }

            // 如果日期为空，默认查询未来30天的日程
            if (startDate == null) {
                startDate = LocalDate.now();
            }
            if (endDate == null) {
                endDate = startDate.plusDays(30);
            }

            // 查询用户的预约记录
            LambdaQueryWrapper<ServiceReservation> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(ServiceReservation::getUserId, userId);
            wrapper.between(ServiceReservation::getReservationDate, startDate, endDate);
            wrapper.in(ServiceReservation::getReservationStatus, Arrays.asList(1, 2, 3, 4)); // 不包括已取消
            wrapper.orderByAsc(ServiceReservation::getReservationDate);
            wrapper.orderByAsc(ServiceReservation::getReservationTime);

            List<ServiceReservation> reservations = reservationMapper.selectList(wrapper);

            // 构建日程列表
            for (ServiceReservation reservation : reservations) {
                ServiceType serviceType = serviceTypeMapper.selectById(reservation.getServiceTypeId());
                Pet pet = petMapper.selectById(reservation.getPetId());

                Map<String, Object> scheduleItem = new HashMap<>();
                scheduleItem.put("id", reservation.getId());
                scheduleItem.put("reservationNo", reservation.getReservationNo());
                scheduleItem.put("date", reservation.getReservationDate().toString());
                scheduleItem.put("time", reservation.getReservationTime() != null ? 
                    reservation.getReservationTime().toString() : "");
                scheduleItem.put("serviceTypeId", reservation.getServiceTypeId());
                scheduleItem.put("serviceTypeName", serviceType != null ? serviceType.getServiceName() : "未知服务");
                scheduleItem.put("serviceDescription", serviceType != null ? serviceType.getDescription() : "");
                scheduleItem.put("petId", reservation.getPetId());
                scheduleItem.put("petName", pet != null ? pet.getPetName() : "未知宠物");
                scheduleItem.put("status", reservation.getReservationStatus());
                scheduleItem.put("statusText", getStatusText(reservation.getReservationStatus()));
                scheduleItem.put("totalAmount", reservation.getTotalAmount());
                scheduleItem.put("specialRequirements", reservation.getSpecialRequirements());
                scheduleItem.put("employeeId", reservation.getEmployeeId());
                scheduleItem.put("createTime", reservation.getCreateTime());

                // 计算距离预约时间还有多久
                if (reservation.getReservationDate() != null && reservation.getReservationTime() != null) {
                    java.time.LocalDateTime reservationDateTime = java.time.LocalDateTime.of(
                        reservation.getReservationDate(), reservation.getReservationTime());
                    java.time.Duration duration = java.time.Duration.between(
                        java.time.LocalDateTime.now(), reservationDateTime);
                    
                    if (duration.isNegative()) {
                        scheduleItem.put("timeRemaining", "已过期");
                        scheduleItem.put("isPast", true);
                    } else {
                        long hours = duration.toHours();
                        long minutes = duration.toMinutes() % 60;
                        if (hours > 24) {
                            long days = hours / 24;
                            scheduleItem.put("timeRemaining", days + "天后");
                        } else if (hours > 0) {
                            scheduleItem.put("timeRemaining", hours + "小时后");
                        } else {
                            scheduleItem.put("timeRemaining", minutes + "分钟后");
                        }
                        scheduleItem.put("isPast", false);
                    }
                } else {
                    scheduleItem.put("timeRemaining", "未知");
                    scheduleItem.put("isPast", false);
                }

                scheduleList.add(scheduleItem);
            }

        } catch (Exception e) {
            log.error("获取用户预约日程失败", e);
        }

        return scheduleList;
    }

    /**
     * 获取预约状态文本
     */
    private String getStatusText(Integer status) {
        if (status == null) {
            return "未知";
        }
        switch (status) {
            case 1:
                return "待确认";
            case 2:
                return "已确认";
            case 3:
                return "进行中";
            case 4:
                return "已完成";
            case 5:
                return "已取消";
            default:
                return "未知";
        }
    }
}

